
import { Lalm } from "./lalm";

//import io from 'socket.io-client';

const audio_samplerate = 48000;


export class Player {
    SERVER_IP = "192.168.1.6";
    //const SERVER_IP = "101.35.53.153";

    constructor(roomId, selfId, pusherId) {
        this.roomId = roomId;
        this.selfPeerId = selfId;
        this.pusherId_ = pusherId;
        this.adecoder_ = null;
        this.vdecoder_ = null;
        this.socket_ = null;

        this.vwriter_ = null;
        this.awriter_ = null;
        
        this.waitKeyframe_ = true;

        this.decoderController = void 0;
        this.decoderReader = null;

        this.set_audio_once = false;

        this.base_timestamp = 0;
        this.audio_palyer_
    }
    async init(videoElement) {
        //this.audio_palyer_ = new WebAudioPlayer({})

        // VideoDecoder config 
        this.vdecoder_ = new VideoDecoder({
            output: this.handleVideoDecoded.bind(this),
            error: (error) => {
                console.error("video decoder " + error);
            }
        });
        const video_config = {
            codec: 'vp8',
            width: 640,
            height: 480,
            framerate: 15,
        };
        this.vdecoder_.configure(video_config);


       

        let vgenerator = new MediaStreamTrackGenerator('video');
        this.vwriter_ = vgenerator.writable.getWriter();

       
        let agenerator = new MediaStreamTrackGenerator('audio');
        this.awriter_ = agenerator.writable.getWriter();


        let processedStream = new MediaStream();
        processedStream.addTrack(vgenerator);
//        processedStream.addTrack(agenerator);
        videoElement.srcObject = processedStream;
//        await videoElement.play();



        self = this;        
        const decoderStream = new ReadableStream({
            start(c) {
            return (self.decoderController = c);
            },
        });
        this.decoderReader = decoderStream.getReader();
  
        // AudioDecoder config 
        this.adecoder_ = new AudioDecoder({
            output: async (frame) => {
                self.decoderController.enqueue(frame.duration);
                await self.awriter_.write(frame);
                    //await self.audio_palyer_.play(frame);
            },
            //output: this.handleAudioDecoded.bind(this),
            error: (error) => {
                console.error("audio decoder " + error);
            }
        });
        this.adecoder_.configure({ codec: 'opus', numberOfChannels: 2, sampleRate: audio_samplerate });
    

        // 前面放在video标签里面声音播放不出来
        this.mediaStream = new MediaStream([agenerator]);
        const audio = document.querySelector('audio');
        audio.srcObject = this.mediaStream;
        await audio.play();

        
        /*
        this.socket_ = new WebSocket("ws://" + this.SERVER_IP + ":8000/sub");
        this.socket_.binaryType = 'arraybuffer';

        this.socket_.onopen = async () => {
            console.log('socket open');
        }  
        this.socket_.onmessage = this.onmessage; 
        */
                
        
        this.msgChannel_ = io.connect();//("ws://" + this.SERVER_IP + ":7000");
        //this.selfPeerId = "viewer" + Math.round(Math.random() * 100000);
        // initiate new  connection
        this.almClient = new Lalm(this.msgChannel_, this.roomId + ":demo-alm", { selfId: this.selfPeerId });
        this.almClient.on("join", ret => console.log("Join result: ", ret));
        this.almClient.on("error", err => console.log("Have error: ", err));
        this.almClient.on("data", (data) => {
            this.onmessage({data:data.buffer});
            
            // Trigger statistics refresh
            // setInterval(onProgress(torrent), 500);
        });
        this.almClient.init().then( ()=> {
            this.almClient.join(this.pusherId_);
        }).catch(error => {
            console.error(error)
        })
    }

    
    onmessage = async (event) => {            
        const chunk = CBOR.decode(event.data);
        if (chunk.kind === 'video') {
            if (this.waitKeyframe_ ){
                if(chunk.type === 'delta'){
                    return;
                }
                this.waitKeyframe_ = false;
                console.log('got first keyframe' + Date.now());
            }
            const encoded = new EncodedVideoChunk(chunk);
            this.vdecoder_.decode(encoded);
        } else {            
            if (!this.set_audio_once) {
                this.base_timestamp = chunk.timestamp;
                this.set_audio_once = true;
                this.adecoder_.configure({ codec: 'opus', format:chunk.format, numberOfChannels: chunk.chan, sampleRate: chunk.sr });
            }
            chunk.timestamp -= this.base_timestamp;
            const encoded = new EncodedAudioChunk(chunk);
            this.adecoder_.decode(encoded);

/*          maybe get several minutes delay ?      
        const { value, done } = await this.decoderReader.read();
            // No specification algorithm for 900 delay between EncodedAudioChunk
            // to avoid writing data too fast to MediaStreamTrackGenerator
            // https://bugs.chromium.org/p/chromium/issues/detail?id=1184070
            // https://bugs.chromium.org/p/chromium/issues/detail?id=1199377
            await new Promise((resolve) =>
              setTimeout(resolve, ((value || 0) / 10 ** 6) * 900)
            );
            */
        }
    }

    async handleVideoDecoded(frame) {
        this.vwriter_.write(frame);
        //console.log('video decoded ' + Date.now());
    }

    async handleAudioDecoded(frame) {
        this.awriter_.write(frame);
    }

    destroy() {
        // adding document unload listener : fires when this client's browser closes the page
        this.almClient.quit();

        if (this.socket_) {
            this.socket_.close();
            this.socket_ = null;
        }
    }
}



class WebAudioPlayer {
    constructor(options) {
        this.context = new AudioContext();
        this.gain = this.context.createGain();
        this.gain.connect(this.context.destination);
        this.context._connections = (this.context._connections || 0) + 1;
        
        this.startTime = 0;
        this.buffer = null;
        this.wallclockStartTime = 0;
        this.volume = 1;
        this.enabled = true;
        
        this.sampleRate = options.sampleRate || 48000;
        this.numberOfChannels = options.numberOfChannels || 2;

        this.sourceNode = this.context.createBufferSource();
        
    }

    play1(data) {

        if (!this.enabled) {
            return;
        }

        this.gain.gain.value = this.volume;

        var buffer = this.context.createBuffer(2, data.length/2, this.sampleRate);
        
    }

    // 播放整个文件数据
    async play3(audioData) {    
        this.context.decodeAudioData(audioData, function(buffer) {
            sourceNode.buffer = buffer;
            sourceNode.connect(audioCtx.destination);
                //source.loop = true;
                sourceNode.start(0);
            }
            , function(e){"Error with decoding audio data" + e.err});
    }

    async play2(decodedAudioData) {
        sourceNode.buffer = decodedAudioData;
        sourceNode.connect(this.context.destination);
        sourceNode.start(0);
    }
}
     
